package com.alibaba.citrus.ots.application.report.ability.facade.config;

import com.alibaba.lattice2.epoch.tenant.DefaultTenant;
import com.alibaba.ttl.TtlRunnable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.validation.constraints.NotNull;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author zhoubc
 * @description: TODO
 * @date 2022/10/17 15:29
 */
@Configuration
public class ThreadPoolReportTaskConfig {

    @Value("${ots.salesReportTaskCorePoolSize:10}")
    private Integer corePoolSize;

    @Value("${ots.salesReportTaskMaxPoolSize:20}")
    private Integer maxPoolSize;

    @Value("${ots.salesReportTaskCorePoolSizeSlowerMode:4}")
    private Integer corePoolSizeSlowerMode;

    @Value("${ots.salesReportTaskMaxPoolSizeSlowerMode:8}")
    private Integer maxPoolSizeSlowerMode;

    @Value("${ots.stockReportTaskCorePoolSize:4}")
    private Integer stockReportCorePoolSize;

    @Value("${ots.stockReportTaskMaxPoolSize:8}")
    private Integer stockReportMaxPoolSize;

    //报表月度销售统计线程池配置
    @Bean("monthSalesReportTaskExecutor")
    public ThreadPoolTaskExecutor monthSalesReportTaskExecutor() {
        ThreadPoolTaskExecutor monthSalesReportTaskExecutor = new ThreadPoolTaskExecutor();
        monthSalesReportTaskExecutor.setCorePoolSize(corePoolSize);
        monthSalesReportTaskExecutor.setMaxPoolSize(maxPoolSize);
        monthSalesReportTaskExecutor.setQueueCapacity(1000);
        monthSalesReportTaskExecutor.setKeepAliveSeconds(60 * 5);
        monthSalesReportTaskExecutor.setThreadNamePrefix("monthSalesReportTaskExecutor--");
        monthSalesReportTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        monthSalesReportTaskExecutor.setAwaitTerminationSeconds(60);
        monthSalesReportTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 使用 TtlRunnable
        monthSalesReportTaskExecutor.setTaskDecorator(this::decorateTenantCode);
        monthSalesReportTaskExecutor.initialize();
        return monthSalesReportTaskExecutor;
    }

    //报表月度销售统计线程池配置
    @Bean("monthSalesReportTaskExecutorSlowerMode")
    public ThreadPoolTaskExecutor monthSalesReportTaskExecutorSlowerMode() {
        ThreadPoolTaskExecutor monthSalesReportTaskExecutor = new ThreadPoolTaskExecutor();
        monthSalesReportTaskExecutor.setCorePoolSize(corePoolSizeSlowerMode);
        monthSalesReportTaskExecutor.setMaxPoolSize(maxPoolSizeSlowerMode);
        monthSalesReportTaskExecutor.setQueueCapacity(1000);
        monthSalesReportTaskExecutor.setKeepAliveSeconds(60 * 5);
        monthSalesReportTaskExecutor.setThreadNamePrefix("monthSalesReportTaskExecutorSlowerMode--");
        monthSalesReportTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        monthSalesReportTaskExecutor.setAwaitTerminationSeconds(60);
        monthSalesReportTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 使用 TtlRunnable
        monthSalesReportTaskExecutor.setTaskDecorator(this::decorateTenantCode);
        monthSalesReportTaskExecutor.initialize();
        return monthSalesReportTaskExecutor;
    }

    //报表进销存统计线程池配置
    @Bean("monthStockReportTaskExecutor")
    public ThreadPoolTaskExecutor monthStockReportTaskExecutor() {
        ThreadPoolTaskExecutor monthSalesReportTaskExecutor = new ThreadPoolTaskExecutor();
        monthSalesReportTaskExecutor.setCorePoolSize(stockReportCorePoolSize);
        monthSalesReportTaskExecutor.setMaxPoolSize(stockReportMaxPoolSize);
        monthSalesReportTaskExecutor.setQueueCapacity(1000);
        monthSalesReportTaskExecutor.setKeepAliveSeconds(60 * 5);
        monthSalesReportTaskExecutor.setThreadNamePrefix("monthStockReportTaskExecutor--");
        monthSalesReportTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        monthSalesReportTaskExecutor.setAwaitTerminationSeconds(60);
        monthSalesReportTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 使用 TtlRunnable
        monthSalesReportTaskExecutor.setTaskDecorator(this::decorateTenantCode);
        monthSalesReportTaskExecutor.initialize();
        return monthSalesReportTaskExecutor;
    }

    /**
     * 多租户开发场景下异步线程池中调用需要包装租户code
     *
     * @param runnable
     * @return
     */
    private @NotNull Runnable decorateTenantCode(Runnable runnable) {
        String tenantCode = DefaultTenant.get();
        return TtlRunnable.get(() -> DefaultTenant.runInScope(tenantCode, runnable));
    }
}
